import logging
from datetime import datetime
from rest_framework.decorators import api_view
from django.http import JsonResponse, HttpResponse
from uiautomation.models import UiFiles, UiReport
from mango_service.tools import get_project_path, sep, is_blank, XTRunner
import time
import os
from django.core.paginator import Paginator
from rest_framework.parsers import JSONParser
from django.http import FileResponse
from django.utils.encoding import smart_str
import mimetypes
from mango_service import settings


@api_view(["post"])
def addCase(request):
    caseFile = request.FILES.get("file").name
    case_name = request.POST.get("case_name")
    functional = request.POST.get("functional")
    if is_blank(case_name) or is_blank(functional):
        return JsonResponse({"message": "用例名称与所属模块不能为空", "code": 403})
    ext = str(caseFile).split(".")[-1]
    times = int(time.time())
    case = f"{times}{case_name}.{ext}"

    # 当前脚本的绝对路径
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    # 构造文件保存路径
    case_path = BASE_DIR + "/integration/testdata/" + case
    data = {
        "case_name": case_name,
        "case_path": "/integration/testdata/" + case,
    }
    # 读取文件
    case_data = request.FILES.get("file").read()

    UiFiles(**data).save()

    with open(case_path, "wb") as f:
        f.write(case_data)
    return JsonResponse({"message": "上传成功", "code": 200})


@api_view(["get"])
def case_list(request):
    data = {}
    case_name = request.GET.get("case_name")
    functional = request.GET.get("functional")
    status = request.GET.get("status")
    page = request.GET.get('page')
    pagesize = request.GET.get('pagesize')

    if not is_blank(case_name):
        data["case_name__contains"] = case_name
    if not is_blank(functional):
        data["functional"] = functional
    if not is_blank(status):
        data["status"] = status

    # 查询用例列表
    cases = UiFiles.objects.filter(**data)
    total = cases.count()

    if is_blank(page) or int(page) < 1:
        page = 1

    if is_blank(pagesize):
        pagesize = 10

    caseObject = Paginator(cases, pagesize)
    caseData = caseObject.page(page)

    info = []
    for case in caseData.object_list:
        case_info = {
            'id': case.id,
            'case_name': case.case_name,
            'create_time': case.create_time.strftime('%Y-%m-%d %H:%M:%S'),
            'functional': case.functional,
            'execute_time': case.execute_time.strftime('%Y-%m-%d %H:%M:%S') if case.execute_time else None,
            'status': case.status,
            'report_generate_time': None,
            'report_path': None,
        }
        try:
            report = UiReport.objects.filter(case_id=case.id).latest('generate_time')
            case_info['report_generate_time'] = report.generate_time.strftime('%Y-%m-%d %H:%M:%S')
            case_info['report_path'] = report.report_path
        except UiReport.DoesNotExist:
            pass

        info.append(case_info)

    return JsonResponse({'status': 200, 'message': '查询成功', 'data': info, 'total': total})


@api_view(["get"])
def execute_case(request):
    case_id = request.GET.get("case_id")
    case = UiFiles.objects.filter(id=case_id).values().first()
    if not case:
        return JsonResponse({"message": "用例不存在", "status": 404})
    settings.CASE_PATH = get_project_path() + case["case_path"]
    case_name = case["case_name"]
    logging.info(f"执行路径{settings.CASE_PATH}")
    print(f"执行路径{settings.CASE_PATH}")
    times = int(time.time())
    report_name = f"{times}.html"
    report_path = sep([r"static\reports", report_name], add_before=True)

    try:
        # 假设 XTRunner 返回执行结果状态码，0 表示成功
        XTRunner(report_name=report_name, title=f"{case_name}测试报告")
        UiReport(case_id=case_id, report_path=report_path, generate_time=datetime.now()).save()
        UiFiles.objects.filter(id=case_id).update(status="2", execute_time=datetime.now())
        return JsonResponse({"message": "执行成功", "report_path": report_path, "status": 200})
    except Exception as e:
        logging.error(f"执行用例时发生错误: {str(e)}")
        return JsonResponse({"message": f"执行用例时发生错误: {str(e)}", "status": 500})


@api_view(["GET"])
def open_report(request):
    # 获取分页参数
    page = request.GET.get('page', 1)
    pagesize = request.GET.get('pagesize', 10)

    reports = UiReport.objects.select_related('case').all().order_by('-generate_time')

    # 应用分页
    paginator = Paginator(reports, pagesize)
    try:
        current_page = paginator.page(page)
    except Exception:
        current_page = paginator.page(1)

    data = []
    for report in current_page.object_list:
        data.append({
            'id': report.id,
            'case_id': report.case.id,
            'case_name': report.case.case_name,  # 从关联的用例获取名称
            'execute_time': report.case.execute_time.strftime(
                '%Y-%m-%d %H:%M:%S') if report.case.execute_time else None,
            'report_path': "http://127.0.0.1:8000" + report.report_path,
            'generate_time': report.generate_time.strftime('%Y-%m-%d %H:%M:%S')
        })

    return JsonResponse({
        "message": "查询成功",
        "reports": data,
        "status": 200,
        "total": paginator.count,
        "current_page": int(page),
        "total_pages": paginator.num_pages
    })


@api_view(["get"])
def download_report(request):
    report_id = request.GET.get("id")
    if not report_id:
        return JsonResponse({"message": "缺少报告ID参数", "status": 400})

    try:
        report = UiReport.objects.get(id=report_id)
    except UiReport.DoesNotExist:
        return JsonResponse({"message": "报告不存在", "status": 404})

    # 获取项目根路径
    project_root = get_project_path()

    # 构建完整文件路径
    file_path = os.path.join(project_root, report.report_path.lstrip('/'))

    # 检查文件是否存在
    if not os.path.exists(file_path):
        return JsonResponse({"message": "文件不存在", "status": 404})

    # 获取文件名
    file_name = os.path.basename(file_path)

    # 确定文件MIME类型
    content_type, _ = mimetypes.guess_type(file_path)
    if not content_type:
        content_type = 'application/octet-stream'

    # 打开文件并返回响应
    try:
        # FileResponse是Django中用于返回文件内容的HTTP响应类
        response = FileResponse(open(file_path, 'rb'))
        response['Content-Type'] = content_type
        response['Content-Disposition'] = f'attachment; filename={smart_str(file_name)}'
        return response
    except Exception as e:
        return JsonResponse({"message": f"下载失败: {str(e)}", "status": 500})


@api_view(["get"])
def download_case(request):
    case_id = request.GET.get("case_id")
    if not case_id:
        return JsonResponse({"message": "缺少用例ID参数", "status": 400})

    try:
        case = UiFiles.objects.get(id=case_id)
    except UiFiles.DoesNotExist:
        return JsonResponse({"message": "用例不存在", "status": 404})

    # 获取项目根路径
    project_root = get_project_path()

    # 构建完整文件路径
    file_path = os.path.join(project_root, case.case_path.lstrip('/'))

    # 检查文件是否存在
    if not os.path.exists(file_path):
        return JsonResponse({"message": "文件不存在", "status": 404})

    # 获取文件名
    file_name = os.path.basename(file_path)

    # 确定文件MIME类型
    content_type, _ = mimetypes.guess_type(file_path)
    if not content_type:
        content_type = 'application/octet-stream'

    # 打开文件并返回响应
    try:
        response = FileResponse(open(file_path, 'rb'))
        response['Content-Type'] = content_type
        response['Content-Disposition'] = f'attachment; filename={smart_str(file_name)}'
        return response
    except Exception as e:
        return JsonResponse({"message": f"下载失败: {str(e)}", "status": 500})


@api_view(["delete"])
def delete_case(request, case_id):
    try:
        case = UiFiles.objects.get(id=case_id)
    except UiFiles.DoesNotExist:
        return JsonResponse({"message": "用例不存在", "status": 404})

    try:
        project_root = get_project_path()
        file_path = os.path.join(project_root, case.case_path.lstrip('/'))

        # 删除用例文件
        if os.path.exists(file_path):
            os.remove(file_path)
            logging.info(f"成功删除用例文件: {file_path}")

        # 删除关联的测试报告
        reports = UiReport.objects.filter(case_id=case_id)
        for report in reports:
            report_file_path = os.path.join(project_root, report.report_path.lstrip('/'))
            if os.path.exists(report_file_path):
                os.remove(report_file_path)
            report.delete()

        # 删除用例记录
        case.delete()
        return JsonResponse({"message": "用例删除成功", "status": 200})

    except Exception as e:
        logging.error(f"删除用例失败: {str(e)}")
        return JsonResponse({"message": f"删除用例失败: {str(e)}", "status": 500})


@api_view(["post"])
def add_report(request):
    """添加报告（手动）"""
    case_name = request.POST.get("case_name")
    report_path = request.POST.get("report_path")

    if not case_name or not report_path:
        return JsonResponse({"message": "用例名称和报告路径不能为空", "status": 400})

    try:
        case = UiFiles.objects.get(case_name=case_name)
        UiReport(
            case=case,
            report_path=report_path,
            generate_time=datetime.now()
        ).save()
        return JsonResponse({"message": "报告添加成功", "status": 200})
    except UiFiles.DoesNotExist:
        return JsonResponse({"message": "用例不存在", "status": 404})
    except Exception as e:
        return JsonResponse({"message": f"添加失败: {str(e)}", "status": 500})


@api_view(["delete"])
def delete_report(request, reportId):
    """删除报告"""
    try:
        report = UiReport.objects.get(id=reportId)
        project_root = get_project_path()
        report_file_path = os.path.join(project_root, report.report_path.lstrip('/'))

        # 删除物理文件
        if os.path.exists(report_file_path):
            os.remove(report_file_path)

        # 删除数据库记录
        report.delete()
        return JsonResponse({"message": "报告删除成功", "status": 200})
    except UiReport.DoesNotExist:
        return JsonResponse({"message": "报告不存在", "status": 404})
    except Exception as e:
        return JsonResponse({"message": f"删除失败: {str(e)}", "status": 500})
